#include "PortManagerTest.h"
#include <memory.h>
#include <sstream>

CPPUNIT_TEST_SUITE_REGISTRATION(CPortManagerTestCase);

void CPortManagerTestCase::setUp()
{
  m_conf = new CConfig();
  m_pman = new CPortManager(*m_conf);
}

void CPortManagerTestCase::tearDown()
{
  delete m_pman;
  delete m_conf;
}

static const char *AUX_FILENAME = "test_config.conf";
static const int SIP_LOWPORT = 45000;
static const int SIP_PORTRANGE = 1000;
static const int RTP_LOWPORT = 46000;
static const int RTP_PORTRANGE = 1000;
static const int OUTOFRANGE_PORT =  5000;

void CPortManagerTestCase::InitTest()
{
  CPPUNIT_ASSERT(m_conf->Init(AUX_FILENAME));
  CPPUNIT_ASSERT(m_pman->Init());
}

//pre-condition je, ze test metody Init musi probehnout uspesne
void CPortManagerTestCase::GetPortTest()
{
  CPPUNIT_ASSERT(m_conf->Init(AUX_FILENAME));
  CPPUNIT_ASSERT(m_pman->Init());

  bool bPorts[SIP_PORTRANGE];
  memset(bPorts, 0, sizeof(bPorts));

  unsigned short usPort;
  // vycerpani celeho rozsahu portu
  for(int i = 0; i < SIP_PORTRANGE; i++) {
    usPort = OUTOFRANGE_PORT;
    CPPUNIT_ASSERT(m_pman->GetPort(false, usPort));
    // kontrola, zda se port zmenil
    CPPUNIT_ASSERT(usPort != OUTOFRANGE_PORT);
    // kontrola, zda je port v rozsahu
    CPPUNIT_ASSERT(usPort >= SIP_LOWPORT && usPort < SIP_LOWPORT + SIP_PORTRANGE);
    // nesmi byt uz pouzity
    CPPUNIT_ASSERT(!bPorts[usPort - SIP_LOWPORT]);
    bPorts[usPort - SIP_LOWPORT] = true;
  }
  // dalsi port uz neni mozne pridelit
  CPPUNIT_ASSERT(!m_pman->GetPort(false, usPort));
  memset(bPorts, 0, sizeof(bPorts));

  // vycerpani celeho rozsahu portu
  for(int i = 0; i < RTP_PORTRANGE; i++) {
    usPort = OUTOFRANGE_PORT;
    CPPUNIT_ASSERT(m_pman->GetPort(true, usPort));
    // kontrola, zda se port zmenil
    CPPUNIT_ASSERT(usPort != OUTOFRANGE_PORT);
    // kontrola, zda je port v rozsahu
    CPPUNIT_ASSERT(usPort >= RTP_LOWPORT && usPort < RTP_LOWPORT + 2 * RTP_PORTRANGE);
    // kontrola, ze je vzdy o 2 vetsi
    CPPUNIT_ASSERT(!((usPort - RTP_LOWPORT) & 0x1));
    // nesmi byt uz pouzity
    CPPUNIT_ASSERT(!bPorts[(usPort - RTP_LOWPORT) / 2]);
    bPorts[(usPort - RTP_LOWPORT) / 2] = true;
  }
  CPPUNIT_ASSERT(!m_pman->GetPort(true, usPort));
}

//pre-condition je, ze test metody Init musi probehnout uspesne
void CPortManagerTestCase::ReleasePortTest()
{
  CPPUNIT_ASSERT(m_conf->Init(AUX_FILENAME));
  CPPUNIT_ASSERT(m_pman->Init());

  // vyzkouseni uvolneni portu mimo rozsah
  CPPUNIT_ASSERT(!m_pman->ReleasePort(false, OUTOFRANGE_PORT));
  CPPUNIT_ASSERT(!m_pman->ReleasePort(true, OUTOFRANGE_PORT));
  // prideleni portu a nasledne uvolneni
  unsigned short usPort;
  CPPUNIT_ASSERT(m_pman->GetPort(false, usPort));
  CPPUNIT_ASSERT(!m_pman->ReleasePort(true, usPort));
  CPPUNIT_ASSERT(m_pman->ReleasePort(false, usPort));
}

